package org.bp.util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.management.OperatingSystemMXBean;

/**
 * 硬件信息收集器
 */
@SuppressWarnings("restriction")
public class HardwareInfoCollector {
    private static Log log = LogFactory.getLog(HardwareInfoCollector.class);

	private static OperatingSystemMXBean osMxBean =
            (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();

    private static int physicalCpuNum = 0;
    private static Pattern physicalIdPat = Pattern.compile(
            "physical\\s+id\\s*:\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
    private static Pattern cpuCoresPat = Pattern.compile(
            "cpu\\s+cores\\s*:\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
    
    public static void main(String[] args) {
		System.out.println("CPU逻辑核数" + logicalCpuCoreNum());
		System.out.println("CPU物理核数" + physicalCpuCoreNum());
		System.out.println("总内存大小" + totalPhysicalMem());
		System.out.println("空闲总内存" + freePhysicalMem());
		System.out.println("CPU核数" + logicalCpuCoreNum());
		System.out.println("CPU利用率" + cpuUsage());
   	}

    /**
     * 获取本机CPU核数，为逻辑核数
     */
    public static int logicalCpuCoreNum() {
        return Runtime.getRuntime().availableProcessors();
    }

    /**
     * 获取本机CPU物理核数
     */
    public static int physicalCpuCoreNum() {
        // Linux下需要依赖proc文件系统
        // 注意只有Linux支持，并且可以人为关闭，Unix系统不支持
        return physicalCpuNum;
    }

    /**
     * 获取系统总内存大小
     */
	public static long totalPhysicalMem() {
        return osMxBean.getTotalPhysicalMemorySize();
    }

    /**
     * 系统空闲总内存
     */
	public static long freePhysicalMem() {
        return osMxBean.getFreePhysicalMemorySize();
    }

    /**
     * CPU利用率
     */
    public static double cpuUsage() {
        return osMxBean.getSystemCpuLoad();
    }

    static {
        if(SystemUtils.isLinux()) {
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        new FileInputStream("/proc/cpuinfo")));

                Set<Integer> cpuIdSet = new HashSet<Integer>();

                String line;
                int cpuId = -1;
                while((line = reader.readLine()) != null) {
                    Matcher mat = physicalIdPat.matcher(line);
                    if (mat.matches()) {
                        cpuId = Integer.valueOf(mat.group(1));
                        continue;
                    }

                    mat = cpuCoresPat.matcher(line);
                    if(!mat.matches() || cpuIdSet.contains(cpuId)) {
                        // 不匹配，或者这个CPU核数已经统计过就跳过
                        continue;
                    }

                    cpuIdSet.add(cpuId);
                    physicalCpuNum += Integer.valueOf(mat.group(1));
                }
                StreamUtils.close(reader);
            } catch (IOException e) {
                log.fatal(e);
            }
        }
    }
}
